﻿using AutoMapper;
using bigscreen_ai_demo.DB;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PropertyChanged;
using SqlSugar;
using SqlSugar.Extensions;
using System.Globalization;
using System.Net.Http;
using System.Net.Http.Json;
using System.Security.Policy;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace bigscreen_ai_demo
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class SxAIWindow : Window
    {
        public DataVM vm = new ();

        public int InputDBTableRowId;
        public int OutPutDBTableRowId;

        public IMapper mapper;
        public Storyboard signAminate;

        public SxAIWindow()
        {
            var configuration = new MapperConfiguration(cfg =>
            {
                cfg.AddProfile<AutoMapperMappingProfile>();
            });

            mapper = configuration.CreateMapper();


            Config.Init();
            var db = new DBContext().Db;
            InputDBTableRowId = db.Queryable<ModelA>().First().Id;
            OutPutDBTableRowId = db.Queryable<ModelA>().First().Id;
            InitializeComponent();
            DataContext = vm;
            //SaveJob();
            //ReadJob();

            signAminate = (Resources["signAminate"] as Storyboard)!;

            //var AA = new ModelAVM();
            //PYHelper.RuntimeRun();

            //System.Diagnostics.Process.Start( @"python.exe", @"D:\work\七彩化工\code\ai\pkl.py 0.0007 - 0.006 284.8125 307 96.140625 57.71875 6.5 0.040993");
            //var oupter =  PYHelper.RunAsync(@"D:\work\七彩化工\code\ai\pkl.py", "0.0007 -0.006 284.8125 307 96.140625 57.71875 6.5 0.040993");        


            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(main); i++)
            {
                // Retrieve child visual at specified index value.
                Visual childVisual = (Visual)VisualTreeHelper.GetChild(main, i);
                if (childVisual.GetType().Name == "MyInput")
                {
                    var bindProerty = BindingOperations.GetBinding(childVisual, MyInput.ValueProperty);
                    if(Config.OutPutKeys.Contains(bindProerty.Path.Path.Replace("ModeA.", ""))){
                        ((MyInput)childVisual).IsReadOnly = true;
                    }
                }

            }
            ReadJob_OUTPUT();
            _=LoadModelA();

            
        }


        async public Task<bool> LoadModelA() {

            var modelA = await new DBContext().Db.Queryable<ModelA>().FirstAsync();
            if (modelA!= null)
            {
                mapper.Map(modelA,vm.ModeA = Config.ModelA_Default);
               
            }else{
                vm.ModeA = Config.ModelA_Default;
            }

            vm.ModeA_OUTPUT = mapper.Map<ModelA_OUTPUT>(vm.ModeA);

            return true;
        }
        async public Task<bool> LoadModelA_OUTPUT()
        {
            var modelProps = vm.ModeA_OUTPUT.GetType().GetProperties();
            Config.modelA_OUTPUT_Maps.ForEach(async (m) =>
            {
                var model = await new DBContext().Db.Queryable<ModelA_OUTPUT>().OrderByDescending(d=>d.Id).FirstAsync(d => d.Type == m.Type);
                if (model != null)
                {
                    m.Keys.ForEach(k =>
                    {
                        var newValue =(string)model.GetType().GetProperty(k)!.GetValue(model);
                        if (!string.IsNullOrWhiteSpace(newValue))
                        {
                            var d = Convert.ToDecimal(newValue);
                            var newValueFixed = decimal.Parse(d.ToString("0.#####"), CultureInfo.InvariantCulture).ToString(CultureInfo.InvariantCulture);
                            vm.ModeA_OUTPUT.GetType().GetProperty(k)!.SetValue(vm.ModeA_OUTPUT, newValueFixed);
                        }
                        
                    });
                }
            });

            return true;
        }
        async public Task<bool> SaveModelA()
        {
            vm.ModeA.Updated = DateTime.Now;

            await Task.Run(() =>
            {
                vm.JobStop = true;
                new DBContext().Db.Updateable<ModelA>(vm.ModeA).Where(d => d.Id == InputDBTableRowId).ExecuteCommand();
                vm.JobStop = false;
                Dispatcher.Invoke(() =>
                {
                    saveSign.BeginStoryboard(signAminate);
                });
            });
            return true;
        }
        public void SaveJob()
        {
            Task.Run(async () =>
            {
                if (!vm.JobStop)
                {

                    var _ = SaveModelA().ContinueWith( t =>
                    {
                        try { 
                            if (t.Result == true)
                            {
                                Dispatcher.Invoke(() =>
                                {
                                    saveSign.BeginStoryboard(signAminate);
                                });
                                //act
                            }
                        }catch (Exception ex)
                        {
                            MessageBox.Show("写失败");
                        }
                       
                    });

                }
                await Task.Delay(Config.SaveJobTime);
                SaveJob();
            });


        }
        public void ReadJob_OUTPUT()
        {
            Task.Run(async () =>
            {
                if (!vm.JobStop)
                {
                        var __ = LoadModelA_OUTPUT().ContinueWith(t =>
                        {
                            try
                            {
                                if (t.Result == true)
                                {
                                    Dispatcher.Invoke(() => 
                                    {
                                        Console.WriteLine("readSign");
                                        readSign.BeginStoryboard(signAminate);
                                    });
                                   
                                    //act
                                }
                            }
                            catch (Exception ex)
                            {
                                MessageBox.Show("读失败");
                            }
                        });


                }
                await Task.Delay(Config.ReadJobTime);
                ReadJob_OUTPUT();
            });


        }

        private void Button_Reg(object sender, RoutedEventArgs e)
        {
            URLProtocol.Reg();
        }

        private void Button_UnReg(object sender, RoutedEventArgs e)
        {
            URLProtocol.UnReg();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            main.Visibility = main.Visibility == Visibility.Visible ? Visibility.Hidden : Visibility.Visible;
        }

        public string PrevArg { get; set; } = "";




        private  async void Changed(object sender, RoutedEventArgs e)
        {
            //vm.ModeA.Created = DateTime.Now;

            //vm.ModeA.Updated = DateTime.Now;

            //await Task.Run(() =>
            //{
            //    vm.JobStop = true;
            //    writeDB.Updateable(vm.ModeA).Where(d => d.Id == writeDBTableRowId).ExecuteCommand();
            //    readDB.Updateable<ModelA_OUTPUT>(vm.ModeA).Where(d => d.Id == readDBTableRowId).ExecuteCommand();
            //    vm.JobStop = false;
            //});

        }

        private void Close(object sender, RoutedEventArgs e)
        {
            Application.Current.Shutdown();   
        }

        private async void Submit(object sender, RoutedEventArgs e)
        {
            //将输入值更新到旧值上
            var allOutKeys= Config.modelA_OUTPUT_Maps.SelectMany(m => m.Keys).ToList();
            typeof(ModelA).GetProperties().ToList().ForEach(k =>
            {
                var inputValue = typeof(ModelA).GetProperty(k.Name).GetValue(vm.ModeA);
                var oldValue = typeof(ModelA).GetProperty(k.Name).GetValue(vm.ModeA_OUTPUT);
                if (inputValue!= oldValue)
                {
                    typeof(ModelA).GetProperty(k.Name)!.SetValue(vm.ModeA_OUTPUT, inputValue);
                }
            });

            SaveModelA();
            SubmitSXAI();

        }

        private void Apply(object sender, RoutedEventArgs e)
        {
            //vm.ModeA = mapper.Map<ModelA>(vm.ModeA_OUTPUT);
            //更新同步out
            Config.modelA_OUTPUT_Maps.ForEach(m =>
            {
                m.Keys.ForEach(k =>
                {
                    var newValue = (string)typeof(ModelA_OUTPUT).GetProperty(k)!.GetValue(vm.ModeA_OUTPUT);
                    if (!string.IsNullOrWhiteSpace(newValue))
                    {
                        typeof(ModelA).GetProperty(k)!.SetValue(vm.ModeA, newValue);
                    }
                    
                });
            });
            SaveModelA();

        }



        //提交到sxai
        async void SubmitSXAI()
        {
            if (!Config.SXAI) return;
            HttpClient client = new HttpClient();
            var submitData = Config.SXAIPostKeys.ToDictionary(
                key => key+ ".PV",
                key => typeof(ModelA).GetProperty(key)?.GetValue(vm.ModeA).ObjToDecimal()
            );
            submitData["PVF_0301.PV"] = 16.32.ObjToDecimal();
            submitData["PVF_0302.PV"] = 36.65.ObjToDecimal();
            var response = await client.PostAsJsonAsync("http://192.168.8.222:8000/predict", submitData);
            var resStr = await response.Content.ReadAsStringAsync();
            // resStr = {"input_variables":{"FT_0301.PV":6.72,"FT_0302.PV":26.59,"FT_0401.PV":361.25,"LT_0301.PV":361.75,"LT_0401.PV":129.55,"LT_0601.PV":138.23,"PVF_0301.PV":16.32,"PVF_0302.PV":36.65},"predictions":{"pressure":{"PT_0301B.PV":{"std":0.0,"unit":"MPa","value":2.0120413303375244},"PT_0301D.PV":{"std":0.0,"unit":"MPa","value":2.018430709838867},"PT_0302.PV":{"std":0.0,"unit":"MPa","value":2.005842447280884},"PT_0303.PV":{"std":2.384185791015625e-07,"unit":"MPa","value":2.0673539638519287},"PT_0401.PV":{"std":0.0,"unit":"MPa","value":1.97750723361969},"PT_0402.PV":{"std":0.0,"unit":"MPa","value":2.0637152194976807},"PT_0501.PV":{"std":0.0,"unit":"MPa","value":1.9829597473144531}},"temperature":{"TT_0301A.PV":{"std":3.814697265625e-06,"unit":"\u2103","value":60.53528594970703},"TT_0301B.PV":{"std":7.62939453125e-06,"unit":"\u2103","value":75.29285430908203},"TT_0301C.PV":{"std":3.814697265625e-06,"unit":"\u2103","value":59.366172790527344},"TT_0301D.PV":{"std":0.0,"unit":"\u2103","value":72.61634063720703},"TT_0301E.PV":{"std":7.62939453125e-06,"unit":"\u2103","value":76.5996322631836},"TT_0302.PV":{"std":7.62939453125e-06,"unit":"\u2103","value":69.63987731933594},"TT_0401.PV":{"std":7.62939453125e-06,"unit":"\u2103","value":71.3906478881836},"TT_0402.PV":{"std":7.62939453125e-06,"unit":"\u2103","value":68.67853546142578},"TT_0403.PV":{"std":7.62939453125e-06,"unit":"\u2103","value":84.67655944824219},"TT_0501.PV":{"std":0.0,"unit":"\u2103","value":3.1395740509033203},"TT_0601.PV":{"std":1.9073486328125e-06,"unit":"\u2103","value":22.119144439697266}}},"status":"success"}

            var res = JsonConvert.DeserializeObject<JObject>(resStr);
            if (res["status"].ToSqlValue() == "'success'")
            {
                // Create dictionary to store temperature values
                var temperatureData = new Dictionary<string, decimal>();
                var temperatures = res["predictions"]["temperature"];
                
                foreach (JProperty temp in temperatures)
                {
                    temperatureData[temp.Name] = temp.Value["value"].Value<decimal>();
                }


                ResMap(vm.ModelA_SXAI, temperatureData);
                
                // Similarly for pressure if needed
                var pressureData = new Dictionary<string, decimal>();
                var pressures = res["predictions"]["pressure"];
                
                foreach (JProperty pressure in pressures)
                {
                    pressureData[pressure.Name] = pressure.Value["value"].Value<decimal>();
                }
                
                ResMap(vm.ModelA_SXAI, pressureData);
                
            }
        }
        public void ResMap(ModelA modelA,Dictionary<string,decimal> obj)
        {

            foreach (var prop in typeof(ModelA).GetProperties())
            {
                if (obj.Keys.Contains(prop.Name+".PV"))
                {
                    prop.SetValue(modelA, obj[prop.Name + ".PV"].ToString());
                }
            }
        }
    }


}